package com.hxwb.chainmaker.rpc.service;

import com.hxwb.chainmaker.rpc.common.MessageResult;
import com.hxwb.chainmaker.rpc.common.UnitString;
import com.hxwb.chainmaker.rpc.config.OwnerConfig;
import com.hxwb.chainmaker.rpc.dao.ChainmakerDao;
import com.hxwb.chainmaker.rpc.dao.CoinDao;
import com.hxwb.chainmaker.rpc.dao.LockMemberWalletDao;
import com.hxwb.chainmaker.rpc.entity.ChainmakerEntity;
import com.hxwb.chainmaker.rpc.entity.Coin;
import com.hxwb.chainmaker.rpc.entity.LockMemberWallet;
import com.hxwb.chainmaker.rpc.param.*;
import com.hxwb.chainmaker.rpc.util.GeneratorUtil;
import com.hxwb.chainmaker.rpc.util.HttpUtils;
import com.hxwb.chainmaker.rpc.util.SHAUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

@Service
public class ChainmakerService {
    @Autowired
    private ChainmakerDao chainmakerDao;
    @Autowired
    private CoinDao coinDao;

    @Autowired
    private LockMemberWalletDao lockMemberWalletDao;

    public String createNewWallet(String UUserId){
        System.out.println("====>  Generate new wallet file for chainmaker.");
        ChainmakerEntity daoByAccount = chainmakerDao.findByUuserId(UUserId);
        if(null != daoByAccount){
            return daoByAccount.getAddress();
        }
        List<ChainmakerEntity> chainmakerEntities = chainmakerDao.findAllByUsed(1);
        if(!CollectionUtils.isEmpty(chainmakerEntities)){
            ChainmakerEntity chainmakerEntity = chainmakerEntities.get(0);
            String address = chainmakerEntity.getAddress();
            String privateKey = SHAUtil.shaEncode(address);
            System.out.println("地址"+UUserId+"::"+chainmakerEntities);
            chainmakerEntity.setUsed(2);//已经使用
            chainmakerEntity.setUuserId(UUserId);
            chainmakerEntity.setPrivateKey(privateKey);
            chainmakerDao.save(chainmakerEntity);
            return address;
        }
        return "ERROR";

    }
    public MessageResult balanceOf(String userId,String symbol){
        String account = "U" + userId;
        //获取用户地址，没有则生成
        String address = this.createNewWallet(account);
        if(address.equals("ERROR")){
            return MessageResult.error(400,"查询失败");
        }
        BalanceOfHttpRes httpRes = HttpUtils.balanceOf(address, symbol);
        if(null == httpRes){
            return MessageResult.error(400,"地址错误");
        }
        MessageResult result = new MessageResult(200, "success");
        result.setData(httpRes);
        return result;
    }

    public MessageResult getBalance(String address){
        List<Coin> coinList = coinDao.findChainmaker();
        List<ChainmakerBalanceRes> httpResList = new ArrayList<>();
        MessageResult result = new MessageResult(200, "success");
        if(CollectionUtils.isEmpty(coinList)){
            return result;
        }
        coinList.forEach(p -> {
            ChainmakerBalanceRes chainmakerBalanceRes = new ChainmakerBalanceRes();
            BalanceOfHttpRes httpRes = HttpUtils.balanceOf(address, p.getName());
            if(null == httpRes){
                throw new RuntimeException("区块链浏览器获取余额错误");
            }
            chainmakerBalanceRes.setAmount(httpRes.getAmount());
            chainmakerBalanceRes.setTxId(httpRes.getTxId());
            chainmakerBalanceRes.setSymbol(p.getName());
            httpResList.add(chainmakerBalanceRes);
        });
        result.setData(httpResList);
        return result;
    }

   public MessageResult transfer(TransferParam transferParam){
       System.out.println(transferParam);
        String toAddress = "";
       String fromAccount = "U" + transferParam.getFromUserId();
       String toAccount = "U" + transferParam.getToUserId();
       ChainmakerEntity from = chainmakerDao.findByUuserId(fromAccount);
       BalanceOfHttpRes httpRes = HttpUtils.balanceOf(from.getAddress(),transferParam.getSymbol());
       if(null != httpRes){
           if(transferParam.getAmount().compareTo(httpRes.getAmount())>0){
               return MessageResult.error(400,"余额不足！");
           }
           //转账
           ChainmakerEntity to = chainmakerDao.findByUuserId(toAccount);
           if(null == to){
               toAddress = this.createNewWallet(toAccount);
           }else{
               toAddress= to.getAddress();
           }
           TransferHttpRes transferHttpRes = HttpUtils.transfer(from.getAddress(),toAddress,from.getPrivateKey(), transferParam.getSymbol(),transferParam.getAmount());
           if(null == transferHttpRes || !transferHttpRes.getResult() || !transferHttpRes.getMessage().equals("OK")){
               return MessageResult.error(400,"转账失败！");
           }

           MessageResult result = new MessageResult(200, "success");
           result.setData(transferHttpRes);
           return result;

       }
       return MessageResult.error(400,"转账参数错误！");
   }

    public MessageResult sync(){
        List<LockMemberWallet> lockMemberWalletList = lockMemberWalletDao.findAll();
        if(CollectionUtils.isEmpty(lockMemberWalletList)){
            return null;
        }
        lockMemberWalletList.forEach(p ->{
            HttpUtils.transferchain(Long.valueOf(58),Long.valueOf(p.getMemberId()),p.getTotal(),p.getCoinUnit());
        });

        return MessageResult.success("成功");
    }
    public MessageResult reSync(){
        List<ChainmakerEntity> chainmakerEntityList = chainmakerDao.findAll();
        if(CollectionUtils.isEmpty(chainmakerEntityList)){
            return null;
        }
        chainmakerEntityList.forEach(p ->{
            BalanceOfHttpRes httpRes = HttpUtils.balanceOf(p.getAddress(), "TIME");
            if(null == httpRes){
                throw new RuntimeException("生活");
            }
            if(httpRes.getAmount().compareTo(new BigDecimal("0")) >0){
                HttpUtils.transfer(p.getAddress(),"0x7a2a5ec5f2ce03d7162285a57857e6ce3425ca77",p.getPrivateKey(),"TIME",httpRes.getAmount());
            }
           });

        return MessageResult.success("成功");
    }
    public MessageResult transferToOwner(TransferToOwnerParam transferToOwnerParam){
        String toAddress = OwnerConfig.OWNER_ADDRESS;
        String fromAccount = "U" + transferToOwnerParam.getFromUserId();
        ChainmakerEntity from = chainmakerDao.findByUuserId(fromAccount);
        BalanceOfHttpRes httpRes = HttpUtils.balanceOf(from.getAddress(), transferToOwnerParam.getSymbol());
        if(null != httpRes){
            if(transferToOwnerParam.getAmount().compareTo(httpRes.getAmount())>0){
                return MessageResult.error(400,"余额不足！");
            }
            TransferHttpRes transferHttpRes = HttpUtils.transfer(from.getAddress(),toAddress,from.getPrivateKey(), transferToOwnerParam.getSymbol(),transferToOwnerParam.getAmount());
            if(null == transferHttpRes || !transferHttpRes.getResult() || !transferHttpRes.getMessage().equals("OK")){
                return MessageResult.error(400,"转账失败！");
            }
            MessageResult result = new MessageResult(200, "success");
            result.setData(transferHttpRes);
            return result;

        }
        return MessageResult.error(400,"转账参数错误！");
    }
    public MessageResult transferTo(TransferToParam transferParam){
        String fromAddress = OwnerConfig.OWNER_ADDRESS;
        String toAddress = "";
        String toAccount = "U" + transferParam.getToUserId();
        BalanceOfHttpRes httpRes = HttpUtils.balanceOf(fromAddress, transferParam.getSymbol());
        if(null != httpRes){
            if(transferParam.getAmount().compareTo(httpRes.getAmount())>0){
                return MessageResult.error(400,"余额不足！");
            }
            //转账
            ChainmakerEntity to = chainmakerDao.findByUuserId(toAccount);
            if(null == to){
                toAddress = this.createNewWallet(toAccount);
            }else{
                toAddress= to.getAddress();
            }
            TransferHttpRes transferHttpRes = HttpUtils.transfer(OwnerConfig.OWNER_ADDRESS,toAddress,OwnerConfig.OWNER_PRIVATE_KEY, transferParam.getSymbol(),transferParam.getAmount());
            if(null == transferHttpRes || !transferHttpRes.getResult() || !transferHttpRes.getMessage().equals("OK")){
                return MessageResult.error(400,"转账失败！");
            }

            MessageResult result = new MessageResult(200, "success");
            result.setData(transferHttpRes);
            return result;

        }
        return MessageResult.error(400,"转账参数错误！");
    }
    public MessageResult transferToAddress(TransferToAddressParam transferToAddressParam){
        String fromAccount = "U" + transferToAddressParam.getFromUserId();
        ChainmakerEntity from = chainmakerDao.findByUuserId(fromAccount);
        if(null != from){
            BalanceOfHttpRes httpRes = HttpUtils.balanceOf(from.getAddress(), transferToAddressParam.getSymbol());
            if(null != httpRes){
                if(transferToAddressParam.getAmount().compareTo(httpRes.getAmount())>0){
                    return MessageResult.error(400,"余额不足！");
                }
                //转账
                TransferHttpRes transferHttpRes = HttpUtils.transfer(from.getAddress(),transferToAddressParam.getToAddress(),from.getPrivateKey(), transferToAddressParam.getSymbol(),transferToAddressParam.getAmount());
                if(null == transferHttpRes || !transferHttpRes.getResult() || !transferHttpRes.getMessage().equals("OK")){
                    return MessageResult.error(400,"转账失败！");
                }

                MessageResult result = new MessageResult(200, "success");
                result.setData(transferHttpRes);
                return result;

            }
        }

        return MessageResult.error(400,"转账参数错误！");
    }

    public MessageResult addHashCodeByUserId(AddHashCodeByUserIdParam addHashCodeByUserIdParam) {
        String account = "U" + addHashCodeByUserIdParam.getUserId();
        String address = "";
        String privateKey = "";
        ChainmakerEntity user = chainmakerDao.findByUuserId(account);
        if(null == user){
            address = this.createNewWallet(account);
            privateKey = SHAUtil.shaEncode(address);
        }else{
            address = user.getAddress();
            privateKey = user.getPrivateKey();
        }
        AddHashCodeRes addHashCodeRes = HttpUtils.addHashCode(address,privateKey,addHashCodeByUserIdParam.getContractName(),addHashCodeByUserIdParam.getHashCode());
        if(null == addHashCodeRes || !addHashCodeRes.getResult() || !addHashCodeRes.getMessage().equals("OK")){
            return MessageResult.error(400,"添加hashCode失败！");
        }
        MessageResult result = new MessageResult(200, "success");
        result.setData(addHashCodeRes.getTxId());
        return result;

    }
    public MessageResult addHashCodeByAddress(AddHashCodeByAddressParam addHashCodeByAddressParam) {
        AddHashCodeRes addHashCodeRes = HttpUtils.addHashCode(addHashCodeByAddressParam.getAddress(),addHashCodeByAddressParam.getPrivateKey(),addHashCodeByAddressParam.getContractName(),addHashCodeByAddressParam.getHashCode());
        if(null == addHashCodeRes || !addHashCodeRes.getResult() || !addHashCodeRes.getMessage().equals("OK")){
            return MessageResult.error(400,"添加hashCode失败！");
        }
        MessageResult result = new MessageResult(200, "success");
        result.setData(addHashCodeRes.getTxId());
        return result;
    }

    public MessageResult getHashCodeList(String address,String contractName) {
        GetHashCodeRes getHashCodeRes = HttpUtils.getHashCodeList(address,contractName);
        MessageResult result = new MessageResult(200, "success");
        result.setData(getHashCodeRes);
        return result;
    }
    public MessageResult getHashCodeListByUserId(Integer userId,String contractName) {
        String account = "U" + userId;
        String address = "";
        ChainmakerEntity user = chainmakerDao.findByUuserId(account);
        if(null == user){
            this.createNewWallet(account);
            return MessageResult.success();
        }else{
            address = user.getAddress();
        }
        GetHashCodeRes getHashCodeRes = HttpUtils.getHashCodeList(address,contractName);
        MessageResult result = new MessageResult(200, "success");
        result.setData(getHashCodeRes);
        return result;
    }
    public MessageResult createAll() {
            List<BigInteger> ids = chainmakerDao.findAllUserId();
            if(CollectionUtils.isEmpty(ids)){
                MessageResult result = new MessageResult(200, "success");
                result.setData(Boolean.TRUE);
                return result;
            }
            for(BigInteger p:  ids) {
                System.out.println("id"+p);
                String uuid = "U" +String.valueOf(p);
                System.out.println("uuid"+uuid);
                this.createNewWallet(uuid);
            }
        MessageResult result = new MessageResult(200, "success");
        result.setData(Boolean.TRUE);
        return result;
    }


    }
